package com.laiketui.common.service.dubbo.plugin.group;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.laiketui.common.api.PublicOrderService;
import com.laiketui.common.api.plugin.PubliceGroupService;
import com.laiketui.common.api.plugin.group.PublicGroupPayService;
import com.laiketui.common.api.plugin.payment.PaymentService;
import com.laiketui.common.mapper.*;
import com.laiketui.core.exception.LaiKeAPIException;
import com.laiketui.core.lktconst.GloabConst;
import com.laiketui.core.utils.tool.DataUtils;
import com.laiketui.core.utils.tool.DateUtil;
import com.laiketui.core.utils.tool.SerializePhpUtils;
import com.laiketui.domain.lktconst.DictionaryConst;
import com.laiketui.domain.lktconst.ErrorCode;
import com.laiketui.domain.order.OrderDetailsModel;
import com.laiketui.domain.order.OrderModel;
import com.laiketui.domain.plugin.group.GoGroupOrderDetailsModel;
import com.laiketui.domain.plugin.group.GoGroupOrderModel;
import com.laiketui.domain.plugin.group.GroupConfigModel;
import com.laiketui.domain.product.GroupOpenModel;
import com.laiketui.domain.product.GroupProductModel;
import com.laiketui.domain.vo.pay.PayCallBackVo;
import com.laiketui.domain.vo.pay.PayVo;
import com.laiketui.root.common.BuilderIDTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 拼团支付
 *
 * @author Trick
 * @date 2021/4/1 9:55
 */
@Service("groupPayService")
public class PublicGroupPayServiceImpl implements PaymentService, PublicGroupPayService {
    private final Logger logger = LoggerFactory.getLogger(PublicGroupPayServiceImpl.class);

    @Autowired
    private GoGroupOrderModelMapper goGroupOrderModelMapper;

    @Autowired
    private GoGroupOrderDetailsModelMapper goGroupOrderDetailsModelMapper;

    @Autowired
    private GroupProductModelMapper groupProductModelMapper;

    @Autowired
    private GroupOpenModelMapper groupOpenModelMapper;

    @Autowired
    private GroupConfigModelMapper groupConfigModelMapper;

    @Autowired
    private PublicOrderService publicOrderService;

    @Autowired
    private PubliceGroupService publiceGroupService;

    @Autowired
    private OrderModelMapper orderModelMapper;

    @Autowired
    private OrderDetailsModelMapper orderDetailsModelMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Map<String, Object> payment(PayVo vo) throws LaiKeAPIException {
        Map<String, Object> resultMap = new HashMap<>(16);
        try {
            Map<String, Object> parmaMap = new HashMap<>(16);
            int count;
            //获取订单信息
            parmaMap.put("sNo", vo.getOrderno());
            parmaMap.put("user_id", vo.getUserId());
            parmaMap.put("store_id", vo.getStoreId());
            parmaMap.put("status", GoGroupOrderModel.OrderStatus.NOTPAY);
            List<Map<String, Object>> orderInfo = goGroupOrderModelMapper.getGrouporder(parmaMap);
            if (orderInfo == null || orderInfo.size() < 1) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_DDBCZ, "订单不存在");
            }
            for (Map<String, Object> order : orderInfo) {
                //订单id
                int orderId = Integer.parseInt(order.get("id").toString());
                //订单模式
                String otype = order.get("pid").toString();
                //支付金额,抵扣金额  支付这里把抵扣金额加进订单金额里,以后就不需再计算金额了
                BigDecimal payAmt = new BigDecimal(order.get("z_price").toString()), offsetBalance = new BigDecimal(order.get("offset_balance").toString());
                payAmt = payAmt.add(offsetBalance);
                //拼团编号
                String ptcode = order.get("ptcode") + "";
                if (GoGroupOrderModel.OrderPid.KAITUAN.toLowerCase().equals(otype)) {
                    //生成拼团编号 15位
                    ptcode = DictionaryConst.OrdersType.ORDERS_HEADER_KT + BuilderIDTool.getNext(BuilderIDTool.Type.NUMBER, 13);
                    //开团流程
                    groupOpenPay(vo.getStoreId(), vo.getUserId(), ptcode, order);
                } else {
                    //校验数据
                    if (payValidata(vo)) {
                        //参团流程
                        groupCanOpenPay(vo.getStoreId(), ptcode);
                    } else {
                        throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_ZFSB, "支付失败");
                    }
                }
                //支付成功修改订单信息
                GoGroupOrderModel goGroupOrderUpdate = new GoGroupOrderModel();
                goGroupOrderUpdate.setId(orderId);
                goGroupOrderUpdate.setPtcode(ptcode);
                goGroupOrderUpdate.setZ_price(payAmt);
                goGroupOrderUpdate.setPay(vo.getPayType());
                goGroupOrderUpdate.setOffset_balance(payAmt);
                goGroupOrderUpdate.setTrade_no(vo.getTradeNo());
                goGroupOrderUpdate.setPay(vo.getPayType());
                goGroupOrderUpdate.setPay_time(new Date());
                count = goGroupOrderModelMapper.updateByPrimaryKeySelective(goGroupOrderUpdate);
                if (count < 1) {
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_ZFSB, "支付失败");
                }
                count = goGroupOrderDetailsModelMapper.updateStatus(vo.getStoreId(), vo.getOrderno(), GoGroupOrderModel.OrderStatus.PT_ING);
                if (count < 1) {
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_ZFSB, "支付失败");
                }
                //返回支付金额
                resultMap.put("payAmt", payAmt);
            }
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            logger.error("拼团订单支付校验 异常", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "payment");
        }
        return resultMap;
    }

    /**
     * 开团支付流程
     *
     * @param storeId -
     * @param userId  -
     * @param ptCode  -
     * @param order   -
     * @throws LaiKeAPIException -
     * @author Trick
     * @date 2021/4/1 16:03
     */
    private void groupOpenPay(int storeId, String userId, String ptCode, Map<String, Object> order) throws LaiKeAPIException {
        try {
            int count;
            //订单id
            int orderId = Integer.parseInt(order.get("id").toString());
            //商品id
            int goodsId = Integer.parseInt(order.get("p_id").toString());
            //拼团编号
            String ptcode = order.get("ptcode").toString();
            //几人团
            int grouMan = Integer.parseInt(order.get("groupman").toString());
            //活动id
            int gpId = Integer.parseInt(order.get("gpId").toString());

            //获取活动信息
            GroupProductModel groupProductModel = groupProductModelMapper.selectByPrimaryKey(gpId);
            Date endDate = new Date();
            Date configDate = new Date();
            //获取拼团配置
            GroupConfigModel groupConfigModel = new GroupConfigModel();
            groupConfigModel.setStore_id(storeId);
            groupConfigModel = groupConfigModelMapper.selectOne(groupConfigModel);
            if (groupConfigModel != null) {
                //时间换算,数据库存的是小时
                long configTime = (groupConfigModel.getGroup_time() * 3600 + DateUtil.getTime()) * 1000;
                configDate = DateUtil.dateFormateToDate(new Date(configTime), GloabConst.TimePattern.YMDHMS);
            }
            //活动参数
            Map<String, Object> groupData = DataUtils.cast(SerializePhpUtils.getUnserializeObj(groupProductModel.getGroup_data(), Map.class));
            if (groupData != null) {
                //结束时间
                endDate = DateUtil.dateFormateToDate(groupData.get("endtime").toString(), GloabConst.TimePattern.YMDHMS);
                //如果设置的结束时间大于配置的时间则用配置的时限
                if (!DateUtil.dateCompare(configDate, endDate)) {
                    endDate = configDate;
                }
            }

            //支付成功修改订单信息
            GoGroupOrderModel goGroupOrderUpdate = new GoGroupOrderModel();
            goGroupOrderUpdate.setId(orderId);
            goGroupOrderUpdate.setStatus(GoGroupOrderModel.OrderStatus.PT_ING);
            goGroupOrderUpdate.setPtstatus(GoGroupOrderModel.Ptstatus.PT_ING);
            count = goGroupOrderModelMapper.updateByPrimaryKeySelective(goGroupOrderUpdate);
            if (count < 1) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_ZFSB, "支付失败");
            }

            //添加一条开团记录
            GroupOpenModel groupOpenSave = new GroupOpenModel();
            groupOpenSave.setStore_id(storeId);
            groupOpenSave.setUid(userId);
            groupOpenSave.setPtgoods_id(goodsId);
            groupOpenSave.setPtcode(ptcode);
            groupOpenSave.setPtnumber(1);
            groupOpenSave.setGroupman(grouMan);
            groupOpenSave.setAddtime(new Date());
            groupOpenSave.setEndtime(endDate);
            groupOpenSave.setPtstatus(GroupOpenModel.Ptstatus.PT_ING);
            groupOpenSave.setGroup_title(groupProductModel.getGroup_title());
            groupOpenSave.setGroup_level(groupProductModel.getGroup_level());
            //O:8:"stdClass":3:{s:9:"starttime";s:19:"2021-03-25 10:38:49";s:8:"overtype";s:1:"2";s:7:"endtime";s:19:"2021-03-31 00:00:00";}
            Map<String, Object> groupDataMap = DataUtils.cast(SerializePhpUtils.getUnserializeObj(groupProductModel.getGroup_data(), Map.class));
            if (groupDataMap != null) {
                //统一结束时间
                groupDataMap.put("endtime", DateUtil.dateFormate(endDate, GloabConst.TimePattern.YMDHMS));
            }
            groupOpenSave.setGroup_data(SerializePhpUtils.JavaSerializeByPhp(groupDataMap));
            groupOpenSave.setActivity_no(groupProductModel.getActivity_no());
            groupOpenSave.setPlatform_activities_id(groupProductModel.getPlatform_activities_id());
            groupOpenSave.setPtcode(ptCode);
            count = groupOpenModelMapper.insertSelective(groupOpenSave);
            if (count < 1) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_ZFSB, "支付失败");
            }
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            logger.error("拼团订单支付校验 异常", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "payment");
        }
    }

    /**
     * 参团支付流程
     *
     * @param storeId -
     * @param ptCode  -
     * @throws LaiKeAPIException -
     * @author Trick
     * @date 2021/4/1 16:03
     */
    private void groupCanOpenPay(int storeId, String ptCode) throws LaiKeAPIException {
        try {
            int count;
            //获取开团信息
            GroupOpenModel groupOpenModel = new GroupOpenModel();
            groupOpenModel.setStore_id(storeId);
            groupOpenModel.setPtcode(ptCode);
            groupOpenModel = groupOpenModelMapper.selectOne(groupOpenModel);
            if (groupOpenModel == null) {
                logger.debug("未找到该拼团 拼团编号{}", ptCode);
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_ZFSB, "支付失败");
            }
            //当前拼团人数
            int currentMan = groupOpenModel.getPtnumber() + 1;
            //几人团
            int groupMan = groupOpenModel.getGroupman();
            if (currentMan <= groupMan) {
                //正常参团,增加人数
                count = groupOpenModelMapper.addPtNum(storeId, ptCode);
                if (count < 1) {
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_ZFSB, "支付失败");
                }
            } else {
                logger.debug("拼团人数已满 当前拼团人数:{}", groupOpenModel.getPtnumber());
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_ZFSBPTRSYM, "支付失败,拼团人数已满");
            }
            if (currentMan == groupMan) {
                //修改订单拼团状态为成功
                count = goGroupOrderModelMapper.updatePtStatus(storeId, ptCode, GoGroupOrderModel.Ptstatus.PT_COMPLETED);
                if (count < 1) {
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_ZFSB, "支付失败");
                }
                //修改订单状态为未收货
                count = goGroupOrderModelMapper.updatePtStatus(storeId, ptCode, GoGroupOrderModel.OrderStatus.NOT_DELIVER);
                if (count < 1) {
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_ZFSB, "支付失败");
                }
                //参团人数达到阈值,拼团成功增加活动销量
                groupProductModelMapper.addVolume(storeId, groupOpenModel.getActivity_no());
                //修改拼团状态
                GroupOpenModel groupOpenUpdate = new GroupOpenModel();
                groupOpenUpdate.setId(groupOpenModel.getId());
                groupOpenUpdate.setPtstatus(GroupOpenModel.Ptstatus.PT_SUCCESS);
                count = groupOpenModelMapper.updateByPrimaryKeySelective(groupOpenUpdate);
                if (count < 1) {
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_ZFSB, "支付失败");
                }
                //拼团成功,把订单写入总订单表
                GoGroupOrderModel groupOrderModel = new GoGroupOrderModel();
                groupOrderModel.setStore_id(storeId);
                groupOrderModel.setPtcode(ptCode);
                groupOrderModel.setPtstatus(GoGroupOrderModel.OrderStatus.PT_ING);
                List<GoGroupOrderModel> goGroupOrderModelList = goGroupOrderModelMapper.select(groupOrderModel);
                for (GoGroupOrderModel goGroupOrder : goGroupOrderModelList) {
                    //复制相同字段的值
                    OrderModel orderSave = JSON.parseObject(JSON.toJSONString(goGroupOrder), new TypeReference<OrderModel>() {
                    });
                    orderSave.setPay_time(new Date());
                    count = orderModelMapper.insertSelective(orderSave);
                    if (count < 1) {
                        throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_ZFSB, "支付失败");
                    }
                    //写入明细
                    GoGroupOrderDetailsModel goGroupOrderDetailsModel = new GoGroupOrderDetailsModel();
                    goGroupOrderDetailsModel.setStore_id(storeId);
                    goGroupOrderDetailsModel.setR_sNo(goGroupOrder.getsNo());
                    List<GoGroupOrderDetailsModel> goGroupOrderDetailsModelList = goGroupOrderDetailsModelMapper.select(goGroupOrderDetailsModel);
                    for (GoGroupOrderDetailsModel groupOrderDetails : goGroupOrderDetailsModelList) {
                        //复制相同字段的值
                        OrderDetailsModel orderDetailsSave = JSON.parseObject(JSON.toJSONString(groupOrderDetails), new TypeReference<OrderDetailsModel>() {
                        });
                        orderDetailsSave.setAdd_time(new Date());
                        count = orderDetailsModelMapper.insertSelective(orderDetailsSave);
                        if (count < 1) {
                            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_ZFSB, "支付失败");
                        }
                    }
                }
            } else {
                //修改订单拼团状态为拼团中
                count = goGroupOrderModelMapper.updatePtStatus(storeId, ptCode, GoGroupOrderModel.Ptstatus.PT_ING);
                if (count < 1) {
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_ZFSB, "支付失败");
                }
            }
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            logger.error("参团订单支付校验 异常", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "groupCanOpenPay");
        }
    }

    @Override
    public boolean payValidata(PayVo vo) throws LaiKeAPIException {
        try {
            int count;
            Map<String, Object> parmaMap = new HashMap<>(16);
            //获取订单信息
            parmaMap.put("sNo", vo.getOrderno());
            parmaMap.put("user_id", vo.getUserId());
            parmaMap.put("store_id", vo.getStoreId());
            parmaMap.put("status", GoGroupOrderModel.OrderStatus.NOTPAY);
            List<Map<String, Object>> orderInfo = goGroupOrderModelMapper.getGrouporder(parmaMap);
            if (orderInfo == null || orderInfo.size() < 1) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_DDBCZ, "订单不存在");
            }
            int activityId = 0;
            //拼团只会有一个商品,只会循环一次
            for (Map<String, Object> order : orderInfo) {
                //订单id
                int orderId = Integer.parseInt(order.get("id").toString());
                //活动id
                activityId = Integer.parseInt(order.get("activity_no").toString());
                //活动状态
                int ptStatus = Integer.parseInt(order.get("g_status").toString());
                //活动过期时间
                Date endDate = DateUtil.dateFormateToDate(order.get("endtime").toString(), GloabConst.TimePattern.YMDHMS);

                //判断活动是否在拼团中
                if (GroupProductModel.GROUP_GOODS_STATUS_UNDER_WAY == ptStatus) {
                    //判断活动是否过期
                    if (DateUtil.dateCompare(endDate, new Date())) {
                        //校验通过
                        GoGroupOrderModel goGroupOrderModel = new GoGroupOrderModel();
                        goGroupOrderModel.setId(orderId);
                        goGroupOrderModel.setPay(vo.getPayType());
                        String orderno = publicOrderService.createOrderNo(DictionaryConst.OrdersType.ORDERS_HEADER_PT);
                        goGroupOrderModel.setReal_sno(orderno);
                        goGroupOrderModel.setRemark(vo.getRemark());
                        count = goGroupOrderModelMapper.updateByPrimaryKeySelective(goGroupOrderModel);
                        if (count < 1) {
                            logger.debug("拼团订单{} 修改支付信息失败", vo.getOrderno());
                            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常");
                        }
                        return true;
                    } else {
                        logger.debug("拼团订单{}正在支付前校验,校验失败:活动已过期", vo.getOrderno());
                    }
                } else {
                    logger.debug("拼团订单{}正在支付前校验,校验失败:订单状态不在待支付状态", vo.getOrderno());
                }
            }
            //关闭订单
            goGroupOrderModelMapper.updateStatus(vo.getStoreId(), vo.getOrderno(), GoGroupOrderModel.OrderStatus.ORDER_CLOSE);
            count = goGroupOrderDetailsModelMapper.updateStatus(vo.getStoreId(), vo.getOrderno(), GoGroupOrderModel.OrderStatus.ORDER_CLOSE);
            if (count < 1) {
                logger.debug("拼团订单{} 订单关闭失败", vo.getOrderno());
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常");
            }
            //回滚库存
            publiceGroupService.reBackGoodsNum(vo.getStoreId(), vo.getOrderno(), activityId, "拼团订单关闭");
        } catch (Exception e) {
            logger.error("拼团订单支付校验 异常", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "payValidata");
        }
        return false;
    }

    @Override
    public Map<String, Object> callBack(PayCallBackVo vo) throws LaiKeAPIException {
        return null;
    }

}

